package cn.hicard.risk.action.limit;

import java.io.ByteArrayOutputStream;
import java.util.ArrayList;
import java.util.List;
import org.apache.log4j.Logger;
import cn.hicard.risk.common.Constant;
import cn.hicard.core.Page;
import cn.hicard.core.PageResult;
import cn.hicard.core.Where;
import cn.hicard.risk.entity.BdMerchinfo;
import cn.hicard.risk.entity.LimitFreezeinfo;
import cn.hicard.risk.interf.limit.FreezeInfoInterf;
import cn.hicard.risk.interf.limit.RiskLimitFreezeInterface;
import cn.hicard.risk.report.ReportTemplet;
import cn.hicard.risk.service.bd.MerchInfoService;
import cn.hicard.risk.service.limit.LimitFreezeinfoService;
import cn.hicard.util.AppConfig;
import cn.hicard.util.DataTran;
import cn.hicard.util.DateHelp;
import cn.hicard.util.WmgwSms;

/**
 * 商户清算资金限额处理相关供FLEX调用的类
 * 
 * @author zhangyu
 * 
 */
public class LimitFreezeinfoFlex {
	
	private static Logger logger = Logger.getLogger(Constant.LOGGER_MAIN);

	private LimitFreezeinfoService limitFreezeinfoService;
	
	private MerchInfoService merchInfoService;

	public void setMerchInfoService(MerchInfoService merchInfoService) {
		this.merchInfoService = merchInfoService;
	}

	
	/** 银行卡1*/
	public static final String ALL= "1";
	/** 信用卡*/
	public static final String CREDIT= "0";

	/**
	 * 查询商户限额详细信息 分页
	 * 
	 * @param wpmerchno
	 * @param merchname
	 * @param date
	 * @param page
	 * @return
	 * @throws Exception
	 */
	public PageResult<LimitFreezeinfo> search(String wpmerchno,
			String merchname, String startDate, String endDate,Page page) throws Exception {

		Where where = new Where(LimitFreezeinfo.class);
		where.addEqual("wpmerchno", wpmerchno.trim());
		where.addLike("merchname", merchname.trim());
		where.addBetween("cleardate", startDate.trim(),endDate.trim());
 
		try {
			return limitFreezeinfoService.findPage(where, page);

		} catch (Exception e) {
			logger.error("查询:商户限额信息发生异常", e);
			throw e;
		}
	}

	/**
	 * 查询商户限额冻结解冻报表信息
	 * 
	 * @param wpmerchno
	 * @param merchname
	 * @param date
	 * @param page
	 * @return
	 * @throws Exception
	 */
	public List<LimitFreezeinfo> searchReportInfo(String wpmerchno,
			String merchname, String startDate, String endDate) throws Exception {

		Where where = new Where(LimitFreezeinfo.class);
		where.addEqual("wpmerchno", wpmerchno);
		where.addLike("merchname", merchname);
		where.addBetween("cleardate", startDate.trim(),endDate.trim());

		try {
			return limitFreezeinfoService.findReportList(where);

		} catch (Exception e) {
			logger.error("查询:商户限额报表信息发生异常", e);
			throw e;
		}
	}

	/**
	 * 查询上个工作日某商户限额信息
	 * 
	 * @param wpmerchno
	 * @param merchname
	 * @return
	 * @throws Exception
	 */
	public LimitFreezeinfo findPreFreezeInfo(String wpmerchno)
			throws Exception {

		Where where = new Where(LimitFreezeinfo.class);
		where.addEqual("wpmerchno", wpmerchno.trim());
		where.addNotEqual("cleardate", DateHelp.date());

		try {
			return limitFreezeinfoService.findPreFreezeInfo(where);

		} catch (Exception e) {
			logger.error("查询:上一工作日商户限额信息发生异常", e);
			throw e;
		}
	}

	/**
	 * 查询某商户当日信息
	 * 
	 * @param wpmerchno
	 * @return
	 * @throws Exception
	 */
	public LimitFreezeinfo searchTodayInfo(String wpmerchno) throws Exception {
		LimitFreezeinfo freezeInfo = null;
		Where where = new Where(LimitFreezeinfo.class);
		where.addEqual("wpmerchno", wpmerchno.trim());
		where.addLike("freezetime", DateHelp.date().trim());

		try {
			freezeInfo = limitFreezeinfoService.findPreFreezeInfo(where);

		} catch (Exception e) {
			logger.error("查询:当日商户限额信息发生异常", e);
			throw e;
		}

		return freezeInfo;
	}

	/**
	 * 下载报表
	 * 
	 * @param wpmerchno
	 * @param merchname
	 * @param date
	 * @return
	 * @throws Exception
	 */
	public byte[] downLoadLimitInfo(String wpmerchno, String merchname,
			String startDate, String endDate) throws Exception {
		// 报表模板
		ReportTemplet rt = new ReportTemplet();
		// 模板的数据源
		List<LimitFreezeinfo> list = null;
		try {
			list = searchReportInfo(wpmerchno.trim(), merchname.trim(), startDate
					.trim(),endDate.trim());
		} catch (Exception e) {
			logger.error("下载 商户清算资金限额报表 发生异常", e);
			throw e;
		}

		String title = "商户清算资金限额报表";
		ByteArrayOutputStream os = rt.createLimitFreezeTemplet(list, title);

		return os.toByteArray();
	}

	/**
	 * 从商户系统表 获取商户日/月限额基本信息
	 * 查询商户表 条件：日限额、月限额不为空的商户
	 * 查询结果List<>：商户号 终端号 日限额 、类型 月限额 、类型	
	 * @return
	 * @throws Exception 
	 */
	public List<LimitFreezeinfo> getMerchList() {
	
		List<BdMerchinfo> listMerch = new ArrayList<BdMerchinfo>();
		List<LimitFreezeinfo> merchVoList = new ArrayList<LimitFreezeinfo>();
		try {
		listMerch = merchInfoService.findLimitMerch();		
		
		logger.info("从商户系统成功查询" + listMerch.size() + "条限额基本信息");
	
		if(listMerch!=null && listMerch.size()!=0){
			for(int i=0;i<listMerch.size();i++){
				LimitFreezeinfo infoVO = new LimitFreezeinfo();
				infoVO.setWpmerchno(listMerch.get(i).getHmId());//汇卡商户号
				infoVO.setMerchname(listMerch.get(i).getHmName());
			
				if(!"".equals(listMerch.get(i).getDayliquidation())&&listMerch.get(i).getDayliquidation() != null){
					infoVO.setDaylimit(listMerch.get(i).getDayliquidation());
					infoVO.setDaylimittype(ALL);
					infoVO.setMonthlimit(listMerch.get(i).getMonthliquidation());
					infoVO.setMonthlimittype(ALL);
				}else if(!"".equals(listMerch.get(i).getDayclearinglimits())&&listMerch.get(i).getDayclearinglimits()!= null){
					infoVO.setDaylimit(listMerch.get(i).getDayclearinglimits());
					infoVO.setDaylimittype(CREDIT);
					infoVO.setMonthlimit(listMerch.get(i).getMonthclearinglimits());
					infoVO.setMonthlimittype(CREDIT);
				}else{
					infoVO.setDaylimittype("");
					infoVO.setMonthlimittype("");
				}
				merchVoList.add(infoVO);
				
			}		
		}
		 } catch (Exception e) {
			 logger.error("获取商户限额基本信息发生错误",e);
		}		

		return merchVoList;

	}
	

    /**
     * 限额信息更新 
     * @return
     */
	public String updateFreezeInfo() {
        
		    StringBuffer returnMsg = new StringBuffer();//返回给前台的错误信息

			List<LimitFreezeinfo> listMerch = getMerchList();//由商户系统获取限额基本信息
			
			if(listMerch.size()==0){
				returnMsg.append("从商户系统获取限额商户列表为空\n");
			}
					 
			//处理所有未清算的工作日交易	    					    
		    String lastClearDate = "";	
		    boolean monthFlag = false;//是否跨月标志
		    int dayNum = 1;//相隔天数
		  try{ 
		    LimitFreezeinfo preInfo = findPreFreezeInfo("");//获取表中最新数据的清算日期		
		    if(preInfo!=null){
		      lastClearDate = preInfo.getCleardate();
		      //yyyy-MM-dd
		      String lastMonth = lastClearDate.substring(5,7);
		      String newMonth = DateHelp.date().substring(5,7);
		      if(!lastMonth.equals(newMonth)){
		    	  monthFlag = true;//日期已跨月
		      }
//		      dayNum = DateHelp.getDays(lastClearDate,DateHelp.date());//两日之间的天数
		    }
		  } catch (Exception e) {
				logger.error("获取表中最新数据的清算日期失败", e);
				returnMsg.append("获取表中最新数据的清算日期失败\n");
		  }
		

			for (int i = 0; i < listMerch.size(); i++) {
				
				LimitFreezeinfo info = listMerch.get(i);

				/**********************************/
				RiskLimitFreezeInterface freezeVo = new RiskLimitFreezeInterface();
				freezeVo.setHmId(info.getWpmerchno());//汇卡商户号
				freezeVo.setMerchName(info.getMerchname());//商户名称
				freezeVo.setCardType(info.getDaylimittype());//卡类型
				freezeVo.setClearDate(DateHelp.date());//清算日期yyyy-MM-dd
				/**********************************/
			
				FreezeInfoInterf interf = new FreezeInfoInterf();
				RiskLimitFreezeInterface freezeInfoFromClear = null;
				
				try {
					  // 调用清算接口1方法
					  // 查询条件：汇卡商户号，商户名称，清算日期，卡类型(0:信用卡,1:所有卡)
					  // 返回信息：汇卡商户号，对应的日清算金额总额
				      freezeInfoFromClear = interf.receiveSumMoney(freezeVo,Constant.INTERF_LIMIT_RECEIVESUM);
				      
				      if (freezeInfoFromClear == null) {
							logger.error("调用清算接口获取" + listMerch.get(i).getWpmerchno()
									+ "商户清算总额发生异常，更新操作继续进行");
							returnMsg.append("获取商户"+listMerch.get(i).getWpmerchno()+"清算总额失败\n");
						}
				      
				  } catch (Exception e) {
					  logger.error("调用清算接口获取" + listMerch.get(i).getWpmerchno()
								+ "商户清算总额发生异常，更新操作继续进行",e);
						returnMsg.append("获取商户"+listMerch.get(i).getWpmerchno()+"清算总额失败\n");
				}
			
				if(freezeInfoFromClear != null){

					double dayLimit = DataTran.strToDouble(listMerch.get(i).getDaylimit());
			
					// 注意商户录入的金额格式
					// 若日限额为0，则不再进行计算
					if (dayLimit!=0) {
						/*****************************/
						long sumDayAmount = freezeInfoFromClear.getSumDayAmount();
						info.setDayamount(DataTran.amtStrTranShow(DataTran.longToStr(sumDayAmount)));// 清算接口获取日应清算金额
						info.setCleardate(DateHelp.date());

						LimitFreezeinfo freezeChange  = null;
					  try {	  info.setDaynum(dayNum);				  
							  if(dayNum>1){
								dayLimit = dayLimit*dayNum;
								info.setDaylimit(DataTran.amtTranShow(dayLimit));// 日限额 = 日限额*相隔天数
							  }		
						  						   				 					  
						    /*****调用核心算法，计算冻结解冻金额****/
						    freezeChange = changeFreezeInfo(info,monthFlag);
					  } catch (Exception e) {
							logger.error("计算商户"+info.getWpmerchno()+"限额失败", e);
							returnMsg.append("计算商户"+info.getWpmerchno()+"限额失败\n");
					  }
					    /*****************************/
                        long freezeMoney = DataTran.strToLong(freezeChange.getDayfreezeamount());
						freezeInfoFromClear.setFreezeMoney(freezeMoney);//冻结金额
						freezeInfoFromClear.setFreezeTime(freezeChange.getFreezetime());//冻结时间
					} else {
						freezeInfoFromClear.setFreezeMoney(0);
						freezeInfoFromClear.setFreezeTime(DateHelp.dateTime());
					}
		
					try {
					  // 调用清算接口2方法 清算保存冻结解冻信息
					  interf.sendFreezeInfo(freezeInfoFromClear,Constant.INTERF_LIMIT_SENDINFO);
					} catch (Exception e) {
						logger.error("调用清算接口发送商户"+info.getWpmerchno()+"限额信息失败", e);
						returnMsg.append("清算获取商户"+info.getWpmerchno()+"限额信息失败\n");
					}
				}
			}

		return returnMsg.toString(); 
	}

	/**
	 * 计算冻结解冻金额
	 * 
	 * @param mid
	 * @param dayAmountStr
	 * @param inputDate
	 * @throws Exception 
	 */
	public LimitFreezeinfo changeFreezeInfo(LimitFreezeinfo freezeInfo,boolean monthFlag) throws Exception {

		try {
					
			double dayAmount = DataTran.strToDouble(freezeInfo.getDayamount());// 某商户今日应清算总额
			String wpmerchno = freezeInfo.getWpmerchno();// 商户号
			double daylimit = DataTran.strToDouble(freezeInfo.getDaylimit());
			double monthlimit = DataTran.strToDouble(freezeInfo.getMonthlimit());

			// 从limit_freezeInfo表获取对应该商户的上一工作日信息
			LimitFreezeinfo preInfo = findPreFreezeInfo(wpmerchno.trim());

			double dayFreezeAmount = 0;
			double totalDateAmount = 0;
			// 未找到上一工作日信息
			if (preInfo != null) {
				dayFreezeAmount = DataTran.strToDouble(preInfo.getDayfreezeamount());// 日冻结(昨日冻结)
				totalDateAmount = DataTran.strToDouble(preInfo.getMonthamount());// 月清算累计和
			}

			double realDayClear = 0;// 实际日清算金额
			double unFreezeToday = 0;// 今日须解冻
			double dateFreezeAmountNew = 0;// 今日须冻结
			double totalDateAmountNew = 0;// 月清算金额（月累计和）
			double monthFreezeAmountNew = 0;// 月限额冻结金额

			// 格式 yyyy-MM-dd
			String dateStr = freezeInfo.getCleardate();

			// 清算日期是否月初一号 yyyy-MM-dd
			if (dateStr.substring(8, 10).equals("01")||monthFlag==true) {
				// 针对休假情况
				if(daylimit>monthlimit){
					// 针对休假情况
					// 今日须冻结 = 今日交易金额+昨日/上月冻结信息-月限额
					dateFreezeAmountNew = dayAmount + dayFreezeAmount - monthlimit;
				}else{
					// 今日须冻结 = 今日交易金额+昨日/上月冻结信息-日限额
					dateFreezeAmountNew = dayAmount + dayFreezeAmount - daylimit;
				}
				

				if (dateFreezeAmountNew < 0) {
					dateFreezeAmountNew = 0;
					
					/******超过日限额发短信*******/
					sendMessage(freezeInfo.getWpmerchno(),"day");
					
				}

				// 今日解冻 = 昨日冻结 - 今日须冻结
				unFreezeToday = dayFreezeAmount - dateFreezeAmountNew;
				if (unFreezeToday < 0) {
					unFreezeToday = 0;
				}

				// 今日实际清算 = 昨日冻结+今日应清 -今日冻结
				realDayClear = dayFreezeAmount + dayAmount - dateFreezeAmountNew;
				// 月清算累计和=今日实际清算
				totalDateAmountNew = realDayClear;
				// 更新 月冻结金额
				monthFreezeAmountNew = dateFreezeAmountNew;

			} else {
				// 不是月初一号

				// 若月累计已超出月限额(月限额存在)
				if (monthlimit!=0 && totalDateAmount >= monthlimit) {
					// 无解冻
					// 今日须冻结 = 今日交易金额+昨日冻结信息
					dateFreezeAmountNew = dayAmount + dayFreezeAmount;
					// 今日实际清算
					realDayClear = 0;
					// 月清算累计和 不变
					totalDateAmountNew = totalDateAmount;
					
					/******超过月限额发短信*******/
					sendMessage(freezeInfo.getWpmerchno(),"month");

				} else {
					// 针对休假情况
					if(daylimit>monthlimit){
						// 今日须冻结 = 今日交易金额+昨日冻结信息-月限额
						dateFreezeAmountNew = dayAmount + dayFreezeAmount - monthlimit;
					}else{
						// 今日须冻结 = 今日交易金额+昨日冻结信息-日限额
						dateFreezeAmountNew = dayAmount + dayFreezeAmount - daylimit;
					}
					

					if (dateFreezeAmountNew < 0) {
						dateFreezeAmountNew = 0;
						
						/******超过日限额发短信*******/
						sendMessage(freezeInfo.getWpmerchno(),"day");
					}

					// 今日解冻 = 昨日冻结 - 今日须冻结
					unFreezeToday = dayFreezeAmount - dateFreezeAmountNew;
					if (unFreezeToday < 0) {
						unFreezeToday = 0;
					}

					// 今日实际清算 = 昨日冻结+今日应清 -今日冻结
					realDayClear = dayFreezeAmount + dayAmount
							- dateFreezeAmountNew;
					// 月清算累计和 = 原月清算累计和 + 今日实际清算
					totalDateAmountNew = totalDateAmount + realDayClear;

					// 若计算后 当月实清累计>月限额
					if (monthlimit!=0 && totalDateAmountNew > monthlimit) {
						dateFreezeAmountNew = dateFreezeAmountNew
								+ (totalDateAmountNew - monthlimit);
						// 今日解冻 = 昨日冻结 - 今日须冻结
						unFreezeToday = dayFreezeAmount - dateFreezeAmountNew;
						if (unFreezeToday < 0) {
							unFreezeToday = 0;
						}
						// 今日实际清算 = 昨日冻结+今日应清 -今日冻结
						realDayClear = dayFreezeAmount + dayAmount - dateFreezeAmountNew;
						// 月清算累计和 = 原月清算累计和 + 今日实际清算
						totalDateAmountNew = totalDateAmount + realDayClear;
						
						/******超过月限额发短信*******/
						sendMessage(freezeInfo.getWpmerchno(),"month");
						
					}

				}
				// 更新 月冻结金额
				monthFreezeAmountNew = dateFreezeAmountNew;

			}

			// 组装风控须保存的对象
			freezeInfo.setDayfreezeamount(DataTran.amtTranShow(dateFreezeAmountNew));
			freezeInfo.setRealdayclear(DataTran.amtTranShow(realDayClear));
			freezeInfo.setHisdayfreeze(DataTran.amtTranShow(dayFreezeAmount));
			freezeInfo.setUnfreeze(DataTran.amtTranShow(unFreezeToday));
			freezeInfo.setMonthfreezeamount(DataTran.amtTranShow(monthFreezeAmountNew));
			freezeInfo.setMonthamount(DataTran.amtTranShow(totalDateAmountNew));
			freezeInfo.setFreezetime(DateHelp.dateTime());// yyyy-MM-dd HH:mm:ss
			freezeInfo.setDaylimit(DataTran.amtTranShow(daylimit/freezeInfo.getDaynum()));
			freezeInfo.setMonthlimit(DataTran.amtTranShow(monthlimit));
						
			if(freezeInfo.getDaylimittype().equals(CREDIT)){
				freezeInfo.setDaylimittype("信用卡");
				freezeInfo.setMonthlimittype("信用卡");
			}else{
				freezeInfo.setDaylimittype("银行卡");
				freezeInfo.setMonthlimittype("银行卡");
			}

			// 如果已存在该商户当日冻结信息，计算后则更新，否则保存
			LimitFreezeinfo todayInfo = searchTodayInfo(freezeInfo.getWpmerchno());
			if (todayInfo != null) {
				freezeInfo.setPkFreezeinfo(todayInfo.getPkFreezeinfo());
				// 更新
				limitFreezeinfoService.updateFreezeinfo(freezeInfo);
			} else {
				// 保存
				limitFreezeinfoService.save(freezeInfo);
			}

		} catch (Exception e) {

			logger.error("限额商户" + freezeInfo.getWpmerchno()
					+ "[计算冻结解冻金额]发生异常，更新操作继续进行", e);
			throw new Exception(e.getMessage());
		}
		return freezeInfo;
	}


	/**
	 * 发送对应调单数据的短信
	 * @param callorder
	 */
	private void sendMessage(String wpmerchno,String flag) {
	
		//查询商户数据，以便取得商户手机号
		BdMerchinfo merch = new BdMerchinfo();
		merch.setHmId(wpmerchno);
		try {
			merch = merchInfoService.getOne(merch);
		} catch (Exception e) {
			logger.error("", e);
		}
		if(merch == null){
			logger.error("商户信息为空,不发送短信-#快去看下汇卡商户号为" + wpmerchno + "的商户为什么不存在#");
			return;
		}
		if(merch.getCellphone() == null || merch.getCellphone().trim().length() == 0){
			logger.error("商户手机号为空,不发送短信");
			return;
		}
		
		String message = AppConfig.get("limitfreeze_message_"+flag);

		logger.info("即将给汇卡商户"+merch.getHmId()+"发送到手机号为" + merch.getCellphone() + "的短信内容为：" + message);
		// 发送短信
		String result = WmgwSms.sendMsg(message, merch.getCellphone().trim());
		logger.info("短信发送WebService返回：" + result);
	}
}
